package com.wuming.caiwu.controller.wx;

import com.wuming.caiwu.core.JsonResult;
import com.wuming.caiwu.util.CaptchaUtils;
import com.yuanzhuo.common.core.mapper.BeanMapper;
import com.yuanzhuo.common.core.mapper.JsonMapper;
import com.wm.common.aes.AesException;
import com.wm.common.aes.SHA1;
import com.wm.common.aes.WXBizMsgCrypt;
import com.wm.common.bean.Result;
import com.wm.common.cache.WechartCache;
import com.wm.common.pojo.AccessToken;
import com.wm.common.pojo.JsSign;
import com.wm.common.pojo.PageAccessToken;
import com.wm.common.pojo.resp.WeXinUserInfo;
import com.wm.common.util.GzhUtil;
import com.wm.common.util.QiYeUtil;
import com.wuming.caiwu.core.wx.WeiXinConstant;
import com.wuming.caiwu.model.Member;
import com.wuming.caiwu.security.SecurityHander;
import com.wuming.caiwu.service.MemberService;
import com.wuming.caiwu.util.SHAUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.rmi.RemoteException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("oauth2")
public class WxOAuthController {
    private static Logger logger = LoggerFactory
            .getLogger(WxOAuthController.class);

    @Resource
    private WechartCache wechartCache;

    private JsonMapper jsonMapper = new JsonMapper();

    private static BeanMapper mapper = new BeanMapper();


    @Autowired
    private MemberService memberService;


    /**
     * 公众号URL验证
     *
     * @param request
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return
     * @author zhangyu
     * @date 2016-3-5
     * @time 下午1:39:38
     */
    @RequestMapping("gzhVerifyURL")
    @ResponseBody
    public String gzhVerifyURL(
            HttpServletRequest request,
            @RequestParam(value = "signature", required = false) String signature,
            @RequestParam(value = "timestamp", required = false) String timestamp,
            @RequestParam(value = "nonce", required = false) String nonce,
            @RequestParam(value = "echostr", required = false) String echostr) {
        // http://fztech.net/zx/default/oauth2/gzhVerifyURL.htmls?signature=4&timestamp=df&nonce=dfd&echostr=55
        try {
            //logger.info("微信URL验证输入参数：signature:" + signature + ";timestamp:" + timestamp + ";nonce:" + nonce + ";echostr:" + echostr);
            return echostr;
        } catch (Exception e) {
            // 验证URL失败，错误原因请查看异常
            e.printStackTrace();
            return null;
        }
    }

    @RequestMapping("getJsSign")
    @ResponseBody
    public String getJsSign(@RequestParam String url) {
        Map<String, Object> result = new HashMap<String, Object>();
        AccessToken accessToken = wechartCache.getAccessToken();
        JsSign jsSign = wechartCache.getJsSign();
        if (null != accessToken && null != jsSign) {
            String timestamp = Long.toString(System.currentTimeMillis() / 1000);
            String nonce_str = SHA1.getRandomStr(20);
            String s = "jsapi_ticket=" + jsSign.getJsapiTicket() + "&noncestr="
                    + nonce_str + "&timestamp=" + timestamp + "&url=" + url;
            logger.info("STRING:" + s);
            String signature = null;
            try {
                signature = WXBizMsgCrypt.SHA1(s);
            } catch (AesException e) {
                e.printStackTrace();
            }
            result.put("success", true);
            result.put("appId", WeiXinConstant.APPID);
            result.put("debug", WeiXinConstant.JS_SIGN_DEBUG);
            result.put("timestamp", timestamp);
            result.put("nonceStr", nonce_str);
            result.put("signature", signature);
            //logger.info("获取亲返回的jsSign:" + result);
        } else {
            result.put("success", false);
        }
        return jsonMapper.toJson(result);

    }

    /**
     * 构造参数并将请求重定向到微信API获取登录信息
     *
     * @param index
     * @return
     */
    @RequestMapping("oauth2")
    public String Oauth2API(HttpServletRequest request,
                            @RequestParam String resultUrl) {
        // 此处可以添加获取持久化的数据，如企业号id等相关信息
        String redirectUrl = "";
        if (resultUrl != null) {
            String protAndPath = request.getServerPort() == 80 ? "" : ":"
                    + request.getServerPort();
            String reqUrl = request.getServerName() + protAndPath + request.getContextPath();
            String backUrl = "http://" + reqUrl + "/oauth2/oauth2url.htmls?oauth2url=" + resultUrl;
            redirectUrl = webAuth2Url("snsapi_base", WeiXinConstant.APPID, backUrl);
        }
        //logger.info("微信oauth2转发链接：{}", redirectUrl);
        return "redirect:" + redirectUrl;
    }

    @RequestMapping("oauth2test")
    public String oauth2test(HttpServletRequest request, Model model, RedirectAttributes redirectAttributes,
                             @RequestParam String resultUrl) {
        String openId = "weixinuser_siteWxOpenxJhMzKHwaterIdss";
        Member user = memberService.getMemberByOpenId(openId.replace("weixinuser_", ""));
        if (null == user) {// 没有绑定微信的用户
            redirectAttributes.addFlashAttribute("message", "当前微信号未注册用户!");
            redirectAttributes.addFlashAttribute("messageType", "error");
            return "redirect:/oauth2/toBindUser.htmls?openid=" + openId.replace("weixinuser_", "");
        } else {
            Subject subject = SecurityUtils.getSubject();
            subject.login(new UsernamePasswordToken(openId, ""));
            return "redirect:" + resultUrl;
        }
    }

    /**
     * http://www.hn-coffeecat.cn/huiqianadmin/oauth2/oauth2url.htmls?oauth2url=/wx/member/personMain.htmls
     * 根据code获取Userid后跳转到需要带用户信息的最终页面
     *
     * @param request
     * @param code      获取微信重定向到自己设置的URL中code参数
     * @param oauth2url 跳转到最终页面的地址
     * @return
     */
    @RequestMapping("oauth2url")
    public String Oauth2MeUrl(HttpServletRequest request,
                              @RequestParam(value = "state", required = false) String state,
                              @RequestParam(value = "code", required = false) String code,
                              @RequestParam String oauth2url,
                              RedirectAttributes redirectAttributes, Model model) {
        //logger.info("微信OAUTH2验证返回code:{}及state:{}", code, state);
        if (code == null) {
            model.addAttribute("message", "获取用户微信code失败!");
            model.addAttribute("messageType", "error");
            return "/mobile/showWxMsg";
        }
        PageAccessToken pageAccessToken = GzhUtil.getPageAccessToken(WeiXinConstant.APPID,
                WeiXinConstant.APPSECRET, code);
        logger.info("进入oauth2url，pageAccessToken：{}", pageAccessToken);
        if (null != pageAccessToken) {
            Member user = memberService.getMemberByOpenId(pageAccessToken.getOpenid());
            if (null == user) {// 没有绑定微信的用户/ 没有绑定微信的用户
                //logger.info("微信OAUTH2验证成功，没有绑定微信的用户，转发到指向绑定页面");
                redirectAttributes.addFlashAttribute("message", "当前微信号未绑定用户!");
                redirectAttributes.addFlashAttribute("messageType", "error");
                return "redirect:/oauth2/toBindUser.htmls?openid=" + pageAccessToken.getOpenid();
            } else {
                //logger.info("微信OAUTH2验证成功，并且已邦定，转发到指向页面");
                return "redirect:" + oauth2url;
            }
        } else {// 获取openid失败的情况
            model.addAttribute("message", "获取用户微信id失败!");
            model.addAttribute("messageType", "error");
            return "/mobile/showWxMsg";
        }
    }

    /**
     * 转向用户邦定界面
     *
     * @param openid
     * @param model
     * @return
     * @author zhangyu
     * @date 2016-3-8
     * @time 下午12:04:10
     */
    @RequestMapping("toBindUser")
    public String toBindUser(@RequestParam String openid, Model model) {
        model.addAttribute("openid", openid);
        return "/wx/member/bindMember";
    }

    /**
     * 转向用户邦定成功
     *
     * @return
     * @author zhangyu
     * @date 2016-3-8
     * @time 下午12:04:10
     */
    @RequestMapping("bindSuccess")
    public String bindSuccess() {
        return "/wx/member/bindSuccess";
    }


    /**
     * 用户邦定操作
     *
     * @param ucode
     * @param upasword
     * @param openid
     * @return
     * @throws Exception
     * @author zhangyu
     * @date 2016-3-8
     * @time 下午12:04:13
     */
    @ResponseBody
    @RequestMapping("bindUser")
    public JsonResult bindUser(@RequestParam String ucode, @RequestParam String upasword,
                               @RequestParam String openid) throws Exception {
        upasword = SHAUtil.shaEncode(upasword);
        try {
            Subject subject = SecurityUtils.getSubject();
            subject.login(new UsernamePasswordToken(ucode, upasword));
            Member user = SecurityHander.getCurrentUser();
            AccessToken accessToken = wechartCache.getAccessToken();
            PageAccessToken pageAccessToken = new PageAccessToken();
            pageAccessToken.setOpenid(openid);
            WeXinUserInfo weXinUserInfo = GzhUtil.getWeXinUserInfo(accessToken, pageAccessToken);
            if (null != weXinUserInfo) {
                user.setOpenid(openid);
                memberService.modifyMember(user);
                return new JsonResult(user, "绑定成功.", true);
            } else {
                return new JsonResult(null, "绑定失败.", false);
            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
            return new JsonResult(null, "绑定失败.", false);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult(null, "绑定失败.", false);
        }
    }

    /**
     * 形成网页授权页面链接
     *
     * @param type：snsapi_base和snsapi_userinfo
     * @param appid
     * @param redirect_uri
     * @return
     * @author zhangyu
     * @date 2016-8-13
     * @time 上午8:34:26
     */
    private String webAuth2Url(String type, String appid, String redirect_uri) {
        try {
            redirect_uri = java.net.URLEncoder.encode(redirect_uri, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String oauth2Url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="
                + appid
                + "&redirect_uri="
                + redirect_uri
                + "&response_type=code&scope=" + type + "&state=insurance#wechat_redirect";
        return oauth2Url;
    }

    /**
     * 调用接口获取用户信息
     *
     * @param token
     * @param code
     * @param agentId
     * @return
     * @throws SQLException
     * @throws RemoteException
     */
    public String getMemberGuidByCode(String token, String code, String agentId) {
        Result<String> result = QiYeUtil.oAuth2GetUserByCode(token, code,
                agentId);
        if (result.getErrcode() == "0") {
            if (result.getObj() != null) {
                return result.getObj();
            }
        }
        return "";
    }

    @RequestMapping(value = "validCode")
    @ResponseBody
    public String validCode(HttpServletRequest request) {
        HashMap<String, Object> result = new HashMap<String, Object>();
        if (!CaptchaUtils.verify(request)) {
            result.put("result", false);
        } else {
            result.put("result", true);
        }
        return jsonMapper.toJson(result);
    }


}
